#+TITLE: Emacs config
#+STARTUP: showeverything
#+OPTIONS: toc:2
* TABLE OF CONTENTS :toc:
- [[#load-first][Load first]]
  - [[#package-manager][Package Manager]]
  - [[#quelpa][Quelpa]]
- [[#helpers][Helpers]]
  - [[#sudo-open][Sudo open]]
- [[#look-and-feel][Look and feel]]
  - [[#general][General]]
  - [[#key-bindings][Key bindings]]
  - [[#neotree][NeoTree]]
  - [[#autocomplete][Autocomplete]]
  - [[#font][Font]]
  - [[#ivy][Ivy]]
  - [[#ido][IDO]]
- [[#code][Code]]
  - [[#perl][Perl]]
  - [[#cc][C/C++]]
  - [[#gdb][GDB]]
  - [[#git][Git]]
  - [[#svn][SVN]]
  - [[#cmake][CMake]]
- [[#org-mode][Org mode]]
  - [[#general-1][General]]
  - [[#babel][Babel]]
  - [[#table-of-contents][Table of Contents]]
  - [[#enable-org-bullets][Enable Org Bullets]]

* Load first
** Package Manager
#+begin_src emacs-lisp
  (defvar elpaca-installer-version 0.6)
  (defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
  (defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
  (defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
  (defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
                                :ref nil
                                :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                                :build (:not elpaca--activate-package)))
  (let* ((repo  (expand-file-name "elpaca/" elpaca-repos-directory))
         (build (expand-file-name "elpaca/" elpaca-builds-directory))
         (order (cdr elpaca-order))
         (default-directory repo))
    (add-to-list 'load-path (if (file-exists-p build) build repo))
    (unless (file-exists-p repo)
      (make-directory repo t)
      (when (< emacs-major-version 28) (require 'subr-x))
      (condition-case-unless-debug err
          (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
                   ((zerop (call-process "git" nil buffer t "clone"
                                         (plist-get order :repo) repo)))
                   ((zerop (call-process "git" nil buffer t "checkout"
                                         (or (plist-get order :ref) "--"))))
                   (emacs (concat invocation-directory invocation-name))
                   ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
                                         "--eval" "(byte-recompile-directory \".\" 0 'force)")))
                   ((require 'elpaca))
                   ((elpaca-generate-autoloads "elpaca" repo)))
              (progn (message "%s" (buffer-string)) (kill-buffer buffer))
            (error "%s" (with-current-buffer buffer (buffer-string))))
        ((error) (warn "%s" err) (delete-directory repo 'recursive))))
    (unless (require 'elpaca-autoloads nil t)
      (require 'elpaca)
      (elpaca-generate-autoloads "elpaca" repo)
      (load "./elpaca-autoloads")))
  (add-hook 'after-init-hook #'elpaca-process-queues)
  (elpaca `(,@elpaca-order))

  ;; Install a package via the elpaca macro
  ;; See the "recipes" section of the manual for more details.

  ;; (elpaca example-package)

  ;; Install use-package support
  (elpaca elpaca-use-package
    ;; Enable :elpaca use-package keyword.
    (elpaca-use-package-mode)
    ;; Assume :elpaca t unless otherwise specified.
    (setq elpaca-use-package-by-default t))

  ;; Block until current queue processed.
  (elpaca-wait)

  ;; fix for magit
  (defun +elpaca-unload-seq (e)
    (and (featurep 'seq) (unload-feature 'seq t))
    (elpaca--continue-build e))

  (defun +elpaca-seq-build-steps ()
    (append (butlast (if (file-exists-p (expand-file-name "seq" elpaca-builds-directory))
                         elpaca--pre-built-steps elpaca-build-steps))
            (list '+elpaca-unload-seq 'elpaca--activate-package)))

  (use-package seq :elpaca `(seq :build ,(+elpaca-seq-build-steps)))
  ;; Don't install anything. Defer execution of BODY
  ;; (elpaca nil (message "deferred"))

#+end_src
** Quelpa
#+begin_src emacs-lisp
(use-package quelpa
  :ensure t
  :demand t
  :custom (quelpa-update-melpa-p nil))

(use-package quelpa-use-package
  :ensure t
  :demand t)
#+end_src

* Helpers
** Sudo open
#+begin_src emacs-lisp
(defun sudo-find-file (file-name)
  "Like find file, but opens the file as root."
  (interactive "FSudo Find File: ")
  (let ((tramp-file-name (concat "/sudo::" (expand-file-name file-name))))
    (find-file tramp-file-name)))
#+end_src

* Look and feel
** General
#+begin_src emacs-lisp
(setq visible-bell t)
(setq-default indent-tabs-mode nil)
(setq tab-width 4)                            ;; ширина табов
(setq-default truncate-lines t)
(setq-default truncate-partial-width-windows t)

(setq backup-directory-alist `(("." . "~/.saves")))
(setq inhibit-startup-message t)              ;;не показывать сообщение при старте 
(fset 'yes-or-no-p 'y-or-n-p)                 ;;не заставляйте меня печать yes целиком 
(setq-default tab-width 4)                    ;;поумолчанию
(customize-set-variable 'menu-bar-mode nil)
(customize-set-variable 'tool-bar-mode nil)
(customize-set-variable 'scroll-bar-mode nil)

(global-display-line-numbers-mode 1) ;; номер строки слева
;; (global-visual-line-mode nil)

(load-theme 'tango-dark t)
#+end_src
** Key bindings
#+begin_src emacs-lisp
  (use-package general
    :config 
    (general-define-key
     "M-<up>"    'windmove-up
     "M-<down>"  'windmove-down
     "M-<right>" 'windmove-right
     "M-<left>"  'windmove-left
     "C-x C-b"   'switch-to-buffer
     "C-x f"     'find-file
     "C-<f8>"    'neotree-project-dir)
    (general-def c-mode-base-map
      "C-c o"   'ff-find-other-file
      "<C-tab>" (function company-complete)
      "M-,"     'rtags-location-stack-back
      "M-/"     'rtags-location-stack-forward
      "M-."     'rtags-find-symbol-at-point
      "M-\\"    'rtags-find-references-at-point
      "M-'"     'rtags-find-virtuals-at-point)
    (general-def org-mode-map
      "M-<up>"    'windmove-up
      "M-<down>"  'windmove-down
      "M-<right>" 'windmove-right
      "M-<left>"  'windmove-left)
    )
#+end_src
** NeoTree
#+begin_src emacs-lisp
  (use-package all-the-icons
    :if (display-graphic-p))
  (use-package find-file-in-project
    :ensure t)
  (use-package neotree
    :ensure t
    :init
    (setq neo-theme (if (display-graphic-p) 'icons))
    (setq neo-window-width 40)
    :config
    (add-hook 'neo-after-create-hook
            (lambda (&rest _) (display-line-numbers-mode -1)))

    (defun neotree-project-dir ()
      "Open NeoTree using the git root."
      (interactive)
      (let ((project-dir (ffip-project-root))
            (file-name (buffer-file-name)))
        (if project-dir
            (progn
              (neotree-dir project-dir)
              (neotree-find file-name))
          (message "Could not find git project root.")))))
#+end_src

** Autocomplete 
#+begin_src emacs-lisp
  (use-package company
    :after (rtags)
    :custom (company-dabbrev-downcase nil)
    :config (global-company-mode))
  (use-package company-rtags
    :after (rtags company)
    :config (push 'company-rtags company-backends))
#+end_src
** Font 
#+begin_src emacs-lisp
  (set-face-attribute 'default nil
                      :font "Hack"
                      :height 110
                      :weight 'normal)
  (set-face-attribute 'font-lock-comment-face nil
                      :slant 'italic)
  (set-face-attribute 'font-lock-keyword-face nil
                      :slant 'italic)
#+end_src
** Ivy
#+begin_src emacs-lisp
  (use-package ivy
    :ensure t
    :demand t)
  (use-package ivy-rtags
    :ensure t
    :demand t
    :after (ivy rtags))
#+end_src
** IDO
#+begin_src emacs-lisp
  (use-package ido
    :elpaca nil
    :custom
    (ido-auto-merge-work-directories-length -1)
    (ido-everywhere t)
    (ido-enable-flex-matching t)
    (ido-all-frames nil)
    :config
    (ido-mode 1))
#+end_src



* Code
** Perl
#+begin_src emacs-lisp
(defvaralias 'cperl-indent-level 'tab-width)
(setq-default indent-tabs-mode nil)
(defalias 'perl-mode 'cperl-mode)
(add-to-list 'auto-mode-alist '("\\.\\([pP][Llm]\\|al\\|t\\)\\'" . cperl-mode))
(defalias 'perl-mode 'cperl-mode)
#+end_src

** C/C++
#+begin_src emacs-lisp
  (defvaralias 'c-basic-offset 'tab-width)
  (use-package c-mode
    :elpaca nil
    :no-require t
    :config
      (c-set-offset 'member-init-intro 8)
      (c-set-offset 'member-init-cont 0)
      (c-set-offset 'case-label 4)
      (c-set-offset 'arglist-cont-nonempty 8))

  (use-package rtags
    :ensure t
    :demand t
    :after (ivy)
    :custom
    (rtags-display-result-backend 'ivy))
  (use-package modern-cpp-font-lock
    :ensure t)
#+end_src
** GDB
#+begin_src emacs-lisp
  (use-package gdb-mi
    :elpaca (gdb-mi :host github
                    :repo "dvzubarev/emacs-gdb"
                    ;; :repo "weirdNox/emacs-gdb"
                    :files (:defaults "*.el" "*.c" "*.h" "Makefile"))
    :ensure t    :demand t
    :init
      (fmakunbound 'gdb)
      (fmakunbound 'gdb-enable-debug))
#+end_src
** Git
#+begin_src emacs-lisp
(use-package magit
  :ensure t
  :demand t)
#+end_src
** SVN 
#+begin_src emacs-lisp
  (use-package psvn
    :elpaca (psvn :repo "~/devel/emacs/psvn")
    :custom
    (svn-status-verbose nil))
#+end_src
** CMake
#+begin_src emacs-lisp
  (use-package cmake-mode
    :ensure t)
#+end_src
* Org mode
** General
#+begin_src emacs-lisp
  (use-package org
    :mode (("\\.org$" . org-mode))
    :elpaca nil
    :config
    (progn
      (setq org-support-shift-select 1)))
#+end_src
** Babel
#+begin_src emacs-lisp
  (use-package org-babel
    :no-require
    :elpaca nil
    :config
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((sqlite . t))))
#+end_src
** Table of Contents
#+begin_src emacs-lisp
  (use-package toc-org
      :commands toc-org-enable
      :init (add-hook 'org-mode-hook 'toc-org-enable))
#+end_src

** Enable Org Bullets
#+begin_src emacs-lisp
  (add-hook 'org-mode-hook 'org-indent-mode)
  (use-package org-bullets)
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
#+end_src
